package com.young.testcoroutine

import kotlinx.coroutines.*
import org.junit.Test
import java.io.BufferedReader
import java.io.FileReader

/**
 * Author：young
 * .
 * Time： 2022/9/13 23:42 周二
 * .
 * Desc：协程取消的副作用
 */
class CoroutineTest06 {


    /**
     * 使用 finally 进行资源释放
     */
    @Test
    fun test_release_resource() = runBlocking<Unit> {
        val job = launch {
            try {
                repeat(1000) { i ->
                    println("i = $i")
                    delay(500)
                }
            } finally {
                println("i am finally")
            }
        }

        delay(1000)
        println("准备取消")
        job.cancelAndJoin()
        println("已经取消")

    }

    /**
     * 使用 use 函数进行资源释放
     */
    @Test
    fun test_use_function() = runBlocking<Unit> {
//        // 普通方式
//        val bufferReader = BufferedReader(FileReader("D://hello.txt"))
//        with(bufferReader) {
//            var line: String?
//            try {
//                while (true) {
//                    line = readLine() ?: ""
//                    println("line = $line")
//                }
//            } finally {
//                close()
//            }
//        }
        // 使用 use 函数
        // 普通方式
        val bufferReader = BufferedReader(FileReader("D://hello.txt"))
        with(bufferReader) {
            var line: String?
            use {
                while (true) {
                    line = readLine() ?: ""
                    println("line = $line")
                }
            }
        }
    }


    /**
     * 协程被取消后，正常所有子协程都会被取消，但是要是我们有部分逻辑想在取消后依旧可以执行
     * 那么就会使用 NonCancellable 来标记当前协程不可取消，例如：withContext(NonCancellable) 里包着的逻辑即使协程取消也
     * 是会执行
     *
     * 假设有个常驻任务需要执行，也可以使用 NonCancellable
     */
    @Test
    fun test_cancel_with_none_cancellable() = runBlocking {
        val job = launch {
            try {
                repeat(1000) { i ->
                    println("i = $i")
                    delay(500)
                }
            } finally {
                println("i am finally")
                withContext(NonCancellable) {
                    delay(1000)
                    println("finally 最后")
                }
            }
        }


        delay(1300)
        println("准备取消")
        job.cancelAndJoin()
        println("已经取消")
    }


    /**
     * 让任务超时
     */
    @Test
    fun test_deal_with_timeout() = runBlocking<Unit> {
        withTimeout(1300) {
            repeat(1000) { i ->
                println("i $i")
                delay(500)
            }
        }
    }

    /**
     * 让任务超时，不抛异常，返回 null
     */
    @Test
    fun test_deal_with_timeout_return_null() = runBlocking<Unit> {
        val result = withTimeoutOrNull(1300) {
            repeat(1000) { i ->
                println("i $i")
                delay(500)
            }
            "我是返回值"
        } ?: "young"

        println("result $result")
    }

}